/**从 NestJS 中导入用于创建 WebSocket 的装饰器和装饰器选项 */
import {
    ConnectedSocket,
    MessageBody,
    SubscribeMessage,
    WebSocketGateway,
    WebSocketServer,
} from '@nestjs/websockets';
/** 导入 Socket.IO 库，用于处理 WebSocket 连接和消息*/
import { Server, Socket } from 'socket.io';
/*
   @WebSocketGateway是一个装饰器，用于创建WebSocket网关类。WebSocket网关类是用于处理 
   WebSocket连接和消息的核心组件之一。
   它充当WebSocket服务端的中间人，负责处理客户端发起的连接请求，并定义处理不同类型消息的逻辑
*/
@WebSocketGateway({ cors: { origin: '*' } }) // 允许跨域
/**
 *  EventGateway 类是 WebSocket 网关的实现
 */
export class EventGateway {
    constructor() { }
    /**@WebSocketServer() 装饰器用于标记 server 属性，这个属性将会持有实际的 Socket.IO 服务器实例。用于发送消息到客户端 */
    @WebSocketServer()
    server: Server;

    /**消息处理方法 */
    @SubscribeMessage('newMessage')
    handleMessage(@MessageBody() body: any, @ConnectedSocket() client: Socket) {
        const msg: any = {};
        const { roomId, name, message } = body || {}
        msg.text = message
        msg.name = name
        msg.roomId = roomId
        this.server.to(roomId).emit('newMessage', msg)
    }

    // 离开房间
    @SubscribeMessage('leave')
    handleLeave(@MessageBody() body: any, @ConnectedSocket() client: Socket) {
        const { roomId, name } = body || {}
        // 先广播离开消息给房间内其他人
        this.server.to(roomId).emit('leave', `用户：${name}离开了房间 ${roomId}`);
        client.leave(roomId);
    }

    // 创建房间并加入房间
    @SubscribeMessage('join')
    handleJoin(@MessageBody() body: any, @ConnectedSocket() client: Socket) {
        const { roomId, name } = body || {}
        /**创建房间 只有相同房间id的才会接收到该信息 */
        client.join(roomId);
        // client只能给发送给发起请求的客户端
        // client.emit('join', `用户：${name}加入了房间 ${roomId}`);  
        // 广播消息给除自己以外的所有客户端
        // client.broadcast.emit('join', `用户：${name}加入了房间 ${roomId}`);
        // 使用服务器实例来广播消息给所有客户端
        this.server.to(roomId).emit('join', `用户：${name}加入了房间 ${roomId}`);
    }

    // 获取当前房间的人数
    @SubscribeMessage('getRoomUsers')
    handleGetRoomUsers(@MessageBody() body: any, @ConnectedSocket() client: Socket) {
        const room = this.server.sockets.adapter.rooms.get(body.roomId);
        if (room) {
            this.server.to(body.roomId).emit('getRoomUsers', room.size);
        } else {
            this.server.to(body.roomId).emit('getRoomUsers', 0);
        }
    }
}